package com.snowfeel.sfmall.sys.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.snowfeel.sfmall.core.param.IdParam;
import com.snowfeel.sfmall.core.param.IdsParam;
import com.snowfeel.sfmall.core.vo.Option;
import com.snowfeel.sfmall.core.vo.PageVo;
import com.snowfeel.sfmall.sys.convert.SysDictTypeConvert;
import com.snowfeel.sfmall.sys.dto.SysDictTypeParam;
import com.snowfeel.sfmall.sys.mapper.SysDictTypeMapper;
import com.snowfeel.sfmall.sys.model.SysDictItem;
import com.snowfeel.sfmall.sys.model.SysDictType;
import com.snowfeel.sfmall.sys.query.SysDictTypeQuery;
import com.snowfeel.sfmall.sys.vo.SysDictTypeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 数据字典类型业务实现类
 *
 * @author haoxr
 * @date 2022/10/12
 */
@Service
public class SysDictTypeService extends ServiceImpl<SysDictTypeMapper, SysDictType> {

    @Autowired
    private SysDictItemService dictItemService;

    @Autowired
    private SysDictTypeConvert dictTypeConvert;

    /**
     * 字典分页列表
     *
     * @param query 分页查询对象
     * @return
     */
    public PageVo<SysDictTypeVo> page(SysDictTypeQuery query) {
        // 查询参数
        String keywords = query.getKeywords();

        LambdaQueryWrapper<SysDictType> queryWrapper = new LambdaQueryWrapper<SysDictType>()
                .like(StrUtil.isNotBlank(keywords), SysDictType::getName, keywords)
                .or()
                .like(StrUtil.isNotBlank(keywords), SysDictType::getCode, keywords)
                .select(SysDictType::getId, SysDictType::getName, SysDictType::getCode, SysDictType::getStatus);
        // 查询数据
        Page<SysDictType> page = this.page(new Page<>(query.getPageNo(), query.getPageSize()),
                queryWrapper);

        List<SysDictTypeVo> list = dictTypeConvert.convertVoList(page.getRecords());

        // 实体转换
        PageVo<SysDictTypeVo> pageVo = new PageVo<>();
        pageVo.setPages((int) page.getPages());
        pageVo.setTotal(page.getTotal());
        pageVo.setList(list);
        return pageVo;
    }

    /**
     * 获取字典类型表单详情
     *
     * @param param 字典类型ID
     * @return
     */
    public SysDictTypeVo detail(IdParam param) {
        LambdaQueryWrapper<SysDictType> queryWrapper = new LambdaQueryWrapper<SysDictType>()
                .eq(SysDictType::getId, param.getId())
                .select(SysDictType::getId,
                        SysDictType::getName,
                        SysDictType::getCode,
                        SysDictType::getStatus,
                        SysDictType::getRemark);
        // 获取entity
        SysDictType entity = this.getOne(queryWrapper);
        Assert.isTrue(entity != null, "字典类型不存在");

        // 实体转换
        SysDictTypeVo dictTypeVo = dictTypeConvert.convertVo(entity);
        return dictTypeVo;
    }

    /**
     * 新增字典类型
     *
     * @param dictTypeParam
     * @return
     */
    public boolean create(SysDictTypeParam dictTypeParam) {
        // 实体对象转换 form->entity
        SysDictType entity = dictTypeConvert.convertPo(dictTypeParam);
        // 持久化
        boolean result = this.save(entity);
        return result;
    }


    /**
     * 修改字典类型
     *
     * @param id           字典类型ID
     * @param dictTypeParam 字典类型表单
     * @return
     */
    public boolean update(Long id, SysDictTypeParam dictTypeParam) {
        // 获取字典类型
        SysDictType sysDictType = this.getById(id);
        Assert.isTrue(sysDictType != null, "字典类型不存在");

        SysDictType entity = dictTypeConvert.convertPo(dictTypeParam);
        boolean result = this.updateById(entity);
        if (result) {
            // 字典类型code变化，同步修改字典项的类型code
            String oldCode = sysDictType.getCode();
            String newCode = dictTypeParam.getCode();
            if (!StrUtil.equals(oldCode, newCode)) {
                LambdaUpdateWrapper<SysDictItem> updateWrapper = new LambdaUpdateWrapper<SysDictItem>()
                        .eq(SysDictItem::getTypeCode, oldCode)
                        .set(SysDictItem::getTypeCode, newCode);
                dictItemService.update(updateWrapper);
            }
        }
        return result;
    }

    /**
     * 删除字典类型
     *
     * @param param 字典类型ID列表
     * @return
     */
    @Transactional
    public boolean deleteBatch(IdsParam param) {
        LambdaQueryWrapper<SysDictType> queryWrapper = new LambdaQueryWrapper<SysDictType>()
                .in(SysDictType::getId, param.getIds())
                .select(SysDictType::getCode);
        // 删除字典数据项
        List<String> dictTypeCodes = this.list(queryWrapper)
                .stream()
                .map(dictType -> dictType.getCode())
                .collect(Collectors.toList()
                );
        if (CollectionUtil.isNotEmpty(dictTypeCodes)) {
            LambdaQueryWrapper<SysDictItem> wrapper = new LambdaQueryWrapper<SysDictItem>()
                    .in(SysDictItem::getTypeCode, dictTypeCodes);
            dictItemService.remove(wrapper);
        }
        // 删除字典类型
        boolean result = this.removeByIds(param.getIds());
        return result;
    }

    /**
     * 获取字典类型的数据项
     *
     * @param typeCode
     * @return
     */
    public List<Option> options(String typeCode) {
        LambdaQueryWrapper<SysDictItem> queryWrapper = new LambdaQueryWrapper<SysDictItem>()
                .eq(SysDictItem::getTypeCode, typeCode)
                .select(SysDictItem::getValue, SysDictItem::getName);
        // 数据字典项
        List<SysDictItem> dictItems = dictItemService.list(queryWrapper);

        // 转换下拉数据
        List<Option> options = CollectionUtil.emptyIfNull(dictItems)
                .stream()
                .map(dictItem -> new Option(dictItem.getValue(), dictItem.getName()))
                .collect(Collectors.toList());
        return options;
    }

}




